﻿// Decompiled with JetBrains decompiler
// Type: Netick.SerializationCache
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System;

#nullable disable
namespace Netick;

internal sealed class SerializationCache
{
  private readonly NetickEngine Engine;
  private readonly int VersionsPerEntity;
  public unsafe int* Ptr;
  public long Offset;
  public long CacheWordSize;
  private NativeArray<SerializationCache.CacheElement> Table;
  private NativeArray<int> CachesList;
  private int CachesListCount;
  public readonly int ElementsPerTick;
  public readonly int BitBuffersOffset;
  public readonly int PacketsOffset;
  public readonly int FreshObjectsOffset;

  internal unsafe SerializationCache(NetickEngine engine)
  {
    this.Engine = engine;
    this.VersionsPerEntity = engine._config.MaxSnapshots;
    this.ElementsPerTick = engine._IM.AllGroups.Length + 50;
    int elementsPerTick = this.ElementsPerTick;
    this.BitBuffersOffset = 0;
    this.PacketsOffset = this.ElementsPerTick;
    this.BitBuffersOffset = this.ElementsPerTick * 2;
    this.Table.Allocate((IAllocator) DirectAllocator.Instance, this.ElementsPerTick * 3 * this.VersionsPerEntity);
    this.CachesList.Allocate((IAllocator) DirectAllocator.Instance, this.ElementsPerTick * 3 * this.VersionsPerEntity);
    this.CacheWordSize = 262144L /*0x040000*/;
    this.Ptr = (int*) MemoryAllocation.Allocator.Malloc(this.CacheWordSize * 4L);
  }

  unsafe ~SerializationCache()
  {
    MemoryAllocation.Allocator.Free((void*) this.Ptr);
    this.Table.Deallocate((IAllocator) DirectAllocator.Instance);
    this.CachesList.Deallocate((IAllocator) DirectAllocator.Instance);
  }

  public unsafe void ExpandIfRequired()
  {
    if (this.CacheWordSize - (this.Offset + 10L) > 0L)
      return;
    int* ptr = this.Ptr;
    long cacheWordSize = this.CacheWordSize;
    long num = this.CacheWordSize * 2L;
    int* dest = (int*) MemoryAllocation.Allocator.Malloc(num * 4L);
    MemoryAllocation.Copy((void*) dest, (void*) ptr, cacheWordSize * 4L);
    MemoryAllocation.Free((void*) ptr);
    this.Ptr = dest;
    this.CacheWordSize = num;
  }

  public unsafe void Add(
    long rangeEnd,
    int lastEntityId,
    int entityIndex,
    int count1,
    int count2,
    int tickOffset,
    void* sourceMem,
    int byteSize)
  {
    this.ExpandIfRequired();
    MemoryAllocation.Copy((void*) ((IntPtr) this.Ptr + (IntPtr) (this.Offset * 4L)), sourceMem, (long) byteSize);
    long offset = this.Offset;
    this.Offset += (long) NetickUtils.GetWordSize(byteSize);
    this.AddEntityData(entityIndex, tickOffset, new SerializationCache.CacheElement()
    {
      HasData = 1,
      Count1 = count1,
      Count2 = count2,
      PtrOffset = offset,
      LastWrittenRange = rangeEnd,
      LastEntityId = lastEntityId
    });
  }

  public unsafe void PerformBitBufferCopy(ref WriteData wd, SerializationCache.CacheElement cache)
  {
    int num = wd.Buffer.WritePos >> 3;
    int sizeBytes = (cache.Count1 >> 3) + 1;
    MemoryAllocation.Copy((void*) ((IntPtr) wd.Buffer._chunks + num), (void*) ((IntPtr) this.Ptr + (IntPtr) (cache.PtrOffset * 4L)), (long) sizeBytes);
    wd.Buffer.WritePos += cache.Count1;
    wd.WrittenRangeEnd = cache.LastWrittenRange;
  }

  public unsafe void PerformPacketCopy(Packet targetPkt, SerializationCache.CacheElement cache)
  {
    int count1 = cache.Count1;
    if (targetPkt.Entities.Length < targetPkt.Count + count1)
      targetPkt.Entities.ExpandCapacity((IAllocator) DirectAllocator.Instance);
    MemoryAllocation.Copy((void*) (targetPkt.Entities.GetPtr() + targetPkt.Count), (void*) ((IntPtr) this.Ptr + (IntPtr) (cache.PtrOffset * 4L)), (long) (sizeof (ObjectRecord) * count1));
    targetPkt.Count += count1;
  }

  public bool TryGetData(
    int index,
    int tickOffset,
    out SerializationCache.CacheElement cachedWritten)
  {
    cachedWritten = this.Table[index * this.VersionsPerEntity + tickOffset];
    return cachedWritten.HasData == 1;
  }

  public void AddEntityData(
    int index,
    int tickOffset,
    SerializationCache.CacheElement cachedWritten)
  {
    int i = index * this.VersionsPerEntity + tickOffset;
    this.Table[i] = cachedWritten;
    if (this.CachesListCount >= this.CachesList.Length)
      this.CachesList.ExpandCapacity((IAllocator) DirectAllocator.Instance);
    this.CachesList[this.CachesListCount] = i;
    ++this.CachesListCount;
  }

  public unsafe void Clear()
  {
    SerializationCache.CacheElement* ptr = this.Table.GetPtr();
    for (int i = 0; i < this.CachesListCount; ++i)
      ptr[this.CachesList[i]].HasData = 0;
    this.Offset = 0L;
    this.CachesListCount = 0;
  }

  internal struct CacheElement
  {
    public int HasData;
    public int Count1;
    public int Count2;
    public int LastEntityId;
    public long LastWrittenRange;
    public long PtrOffset;
  }
}
